package com.mycompany.project.client;



import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Random;
import com.smartgwt.client.types.DragAppearance;
import com.smartgwt.client.util.EventHandler;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.DragRepositionMoveEvent;
import com.smartgwt.client.widgets.events.DragRepositionMoveHandler;
import com.smartgwt.client.widgets.events.DragResizeMoveEvent;
import com.smartgwt.client.widgets.events.DragResizeMoveHandler;
import com.smartgwt.client.widgets.events.MouseDownEvent;
import com.smartgwt.client.widgets.events.MouseDownHandler;
import com.smartgwt.client.widgets.events.MouseOutEvent;
import com.smartgwt.client.widgets.events.MouseOutHandler;
import com.smartgwt.client.widgets.events.MouseOverEvent;
import com.smartgwt.client.widgets.events.MouseOverHandler;
import com.smartgwt.client.widgets.events.MouseWheelEvent;
import com.smartgwt.client.widgets.events.MouseWheelHandler;

/**
 * 
 * @author Laboratorio Tv Collaborativa/Contenuti Digitali --> Sardegna District --> Crs4 --> Sardegna Ricerche
 * 
 * This Class implements a single annotation manager. Graphically consist of one AnnotationTag on @SaStria media player and 
 * of one label displayed on AnnotationBar used as a AnnotationTag link. In other words, the Annotation Object is composed
 * of two elements, the AnnotationTag where to read/Write the Video Annotation and the label used on AnnotationBar
 * as visual link to the AnnotationTag. Labels on annotation Bar are ordered according time and ProgrogressBar 
 * Video play progress. This class handles all information about one single annotation as screen position,
 * start and end time in video progress and everything about the annotation. 
 */
public class Annotation {
	
	private AnnotationTag tag;  //Visual AnnotationTag that display the video Annotation
	private Label tagOnBar;   // AnnotationTag link label on Annotation Progress Bar
	private Canvas annotationTagBar;  // pointer to Annotation Progress Bar object in @SaStria Annotation tool.
	private double timeStart; // start time of annotation in video progress.
	private double timeEnd;  // end time of annotation in video progress.
	private double xPosStart; // X start position of AnnotationTag label link in video Annotation progress bar area. 
	private double xPosEnd; // X end position of AnnotationTag label link in video Annotation progress bar area.
	private int yPosTagOnBar; // Y position of AnnotationTag label link in video Annotation progress bar area.
	private double mediaDuration;  // Save the media duration in milliseconds of current video in play. 
	private HandlerManager handleManager;  // handle manager of SaStriaCustomEvent for manage the onAnnotationMoved event.
	private HandlerManager handleManagerAnnotationSaved; // handle manager of AnnotattionSaveEvent for manage the onAnnotationSaved event.
	private HandlerManager handleManagerAnnotKeyWordBlur; // handle manager for fire the AnnotationKeywordBlurEventHandler and consequently the onAnnotationKeyWordBlur event
	private NextActiveTag evidenziableTag; // used on onAnnotationMoved event for send information about the new position to the event listener
	private boolean visible; // if true the annotation is visible on @SaStria video player 
	public static final int HEIGHT_TAGONBAR=10; // Height of label Annotation link on Annotation Progress Bar	
	private int indexOnList; // index of this annotation in Annotations array list
	public static final int ANNOTATION_DEFAULT_LIFE_TIME=10000;  // default size(life time) in milliseconds of annotation.   
	private int previewIndex; // index of annotation preview on annotation preview panel list. 
	private HandlerManager handleManagerTextChange; // handle manager for fire the AnnotationDescrTextChangeEvent and consequently the onTextChange event
 	
	
	
	/**
	 * This method return the Y position of label Annotation link.
	 * @return integer value that represents the Y position of label Annotation link.  
	 */
	public int getYPosTagOnBar(){
		return(yPosTagOnBar);
	}
	
	
	/**
	 * This method return a random color value choosing it between 22 different color.
	 * @return return a string with the name random color.
	 */
	private String getRandomColor(){
		String color;
		
		int valueRandom= Random.nextInt(20);
		
		switch (valueRandom) {
		case 0: color="Crimson";			
				break;
		case 1: color="BlueViolet";			
				break;
		case 2: color="Chartreuse";			
				break;
		case 3: color="Crimson";			
				break;
		case 4: color="DarkViolet";			
				break;
		case 5: color="DeepPink";			
				break;
		case 6: color="DeepSkyBlue";			
				break;
		case 7: color="GreenYellow";			
				break;
		case 8: color="HotPink";			
				break;
		case 9: color="Indigo";			
				break;
		case 10: color="Lavender";			
				break;
		case 11: color="LightSeaGreen";			
				break;
		case 12: color="LimeGreen";			
				break;
		case 13: color="MediumVioletRed";			
				break;
		case 14: color="OrangeRed";			
				break;
		case 15: color="RoyalBlue";			
				break;
		case 16: color="Yellow";			
				break;
		case 17: color="Beige";			
				break;
		case 18: color="Gold";			
				break;
		case 19: color="Linen";			
				break;
		case 20: color="Blue";			
				break;				
		default: color="Green";
				break;
		}
		return(color);
	}
	
	
	
	/**
	 * This method update the status variable about start and end time in video play position and the position of
	 * annotation label link in the annotation progress bar.   
	 */
	private void dragResizeReposition(){
		
		if(!tag.getSelected()) tag.setSelected(true); // if not selected set as selected
		/* 
		 * Set the new time start and end of annotation, according to the media duration and annotation label link progress position.
		 * label link position is align to the actual position of annotation. 
		*/
		timeStart=((float)tagOnBar.getLeft()/(float)annotationTagBar.getOffsetWidth()) * mediaDuration;
		timeEnd=(((float)tagOnBar.getLeft()+(float)tagOnBar.getOffsetWidth())/(float)annotationTagBar.getOffsetWidth())*mediaDuration;
		/* 
		 * Set the new X Start and end position of annotation, according to the media duration and annotation label link progress position.
		 * label link position is align to the actual position of annotation. 
		*/
		xPosStart=tagOnBar.getLeft();
		xPosEnd=xPosStart+tagOnBar.getOffsetWidth();		
		
		//TOGLIERE TOGLIERE TOGLIERE TOGLIERE TOGLIERE TOGLIERE TOGLIERE
		evidenziableTag.setTimeValue(-10);
		
		/*
		 * Save the information about the new annotation position in the evidenziableTag object before to
		 * fire the onAnnotationMoved event. evidenziableTag is used for send information about the new 
		 * annotation position to the event listener. 
		 * */
		evidenziableTag.setIndexValue(tagOnBar.getLeft());  // save the new status position for send it to onAnnotationMoved event listener
		tag.setTimesegment(timeStart, timeStart); // sets new video annotation time interval segment 
		handleManager.fireEvent(new SaStriaCustomEvent(evidenziableTag,previewIndex,timeStart,timeEnd)); // fire onAnnotationMoved event to alert listener.		
	}
	
	
	/**
	 * Constructor of Annotation class that create the AnnotationTag object setting it visible and focused and create
	 * the annotation label link on Annotation Progress Bar. The constructor is also responsible for set up the 
	 * status variable that save information about the current video as video time duration(size), start and end 
	 * time of annotation, X,Y position of annotation Tag. 
	 * @param xPosOnVideo : An integer value that sets the X position of AnotationTag  
	 * @param yPosOnVideo : An integer value that sets the Y position of AnotationTag
	 * @param yPosTOB : An integer value that sets Y position of label link on Annotation progress Bar
	 * @param annotationTB : pointer to annotation progress bar
	 * @param timeS : double value that sets the time start of annotation.
	 * @param mediaDur : double value that sets the current video time duration(size).
	 * 
	 */
	public Annotation(int xPosOnVideo,int yPosOnVideo,int yPosTOB,Canvas annotationTB,double timeS,double mediaDur, int prewInd) {
		
		handleManager=new HandlerManager(null);  // create handle manager of SaStriaCustomEvent for manage the onAnnotationMoved event.
		handleManagerAnnotationSaved=new HandlerManager(null); // create handle manager of AnnotationSaveEvent for manage the onAnnotationSaved event.
		handleManagerTextChange=new HandlerManager(null); // create the handle manager for dispatch the onTextChange event when the user change description on AnnotationTag
		handleManagerAnnotKeyWordBlur=new HandlerManager(null);// create the handle manager for dispatch the onAnnotationKeyWordBlur event when the user change description on AnnotationTag
		mediaDuration=mediaDur;  // sets the media duration of video(time size)
		timeStart=timeS; // sets the start time of annotation. 
		previewIndex=prewInd; // set annotation preview index on annotation preview panel list. 
		
		// according to start time and ANNOTATION_DEFAULT_LIFE_TIME sets the end time of annotation
		if((timeS+ANNOTATION_DEFAULT_LIFE_TIME)>=mediaDur) // end time of annotation cant'be greater than media duration 
			timeEnd=mediaDur - 50;  //-50 else the link label annotation touch the right border of annotation progress bar called annotationTagBar
		else
			timeEnd=timeS+ANNOTATION_DEFAULT_LIFE_TIME;
			
		
		annotationTagBar=annotationTB;  // sets the pointer to annotation progress bar object
		tag=new AnnotationTag(xPosOnVideo,yPosOnVideo,previewIndex,timeStart,timeEnd);  // create a new Visible AnnotationTag.
		tagOnBar=new Label("Visible");   // create the annotation link label and sets the word "visible" on its caption.
		tagOnBar.setCanDragResize(true); // The label annotation link can be resized.
		tagOnBar.setCanDragReposition(true); // The annotation label link can be dragged and repositioned
		/*
		 * There are different types of effects for showing dragging behavior 
		 * OUTLINE : An outline the size of the target object is moved, resized, etc.
		 * TARGET :  The target object is actually moved, resized, etc.
		 * */
		tagOnBar.setDragAppearance(DragAppearance.TARGET); 
		tagOnBar.setKeepInParentRect(true);  // the annotation label link cannot exit by annotationTagBar area. 
		tagOnBar.setBackgroundColor(getRandomColor()); // set the annotation label link as a random color
		tagOnBar.setResizeFrom("L","R");  // the annotation label link can be resized by Left and right border
		evidenziableTag=new NextActiveTag(-1, -1); // initialize evidenziableTag variable. 
		yPosTagOnBar=yPosTOB;  // sets Y position of annotation label link on Annotation progress Bar
		
		
		tagOnBar.addMouseOutHandler(new MouseOutHandler() {  // implement a label link annotation(tagOnBar) onMouseOut listener 			
			@Override
			public void onMouseOut(MouseOutEvent event) {				
				tagOnBar.setStyleName("TagOnBarBox");  // on mouse exit change the StyleName of tagonBar 		
			}
		});		
		
		tagOnBar.addMouseDownHandler(new MouseDownHandler() { // implement a label link annotation(tagOnBar) onMouseDown listener 			
			@Override
			public void onMouseDown(MouseDownEvent event) {  // on mouse down on tagOnBar 						
				tagOnBar.setStyleName("TagOnBarBoxSelected"); // change the StyleName to  TagOnBarBoxSelected
				
				if(!tag.getSelected())      // if AnnotationTag is not selected than set it as selected
					tag.setSelected(true);
				
				evidenziableTag.setIndexValue(tagOnBar.getLeft());  // set the new position before send it to listener				
				handleManager.fireEvent(new SaStriaCustomEvent(evidenziableTag,previewIndex,timeStart,timeEnd)); // fire event and send new position to listener
				
				if(!tag.getIsVisible())  //if tag is not visible then set it as visible
					tag.forceDraw();
			}
		});
		
		tagOnBar.addMouseOverHandler(new MouseOverHandler() { // implement a label link annotation(tagOnBar) onMouseOver listener 			
			@Override
			public void onMouseOver(MouseOverEvent event) { // on mouse over on tagOnBar
				tag.setSelected(true);   // set the annotation tag as selected		
				tagOnBar.setStyleName("TagOnBarBoxSelected");  // change style name as TagOnBarBoxSelected
			}
		});
				
		tagOnBar.addMouseOutHandler(new MouseOutHandler() {	// implement a label link annotation(tagOnBar) onMouseOut listener		
			@Override
			public void onMouseOut(MouseOutEvent event) { // on mouse out on tagOnBar
				tag.setSelected(false);		 // set the annottaionTag as not selected		
			}
		});
		
		tagOnBar.addDragRepositionMoveHandler(new DragRepositionMoveHandler() {	// implement a label link annotation(tagOnBar) onDragRepositionMove listener		
			@Override
			public void onDragRepositionMove(DragRepositionMoveEvent event) {								
				dragResizeReposition();	 // set new annotation status size and position. 	  
			}
		});
		
		tagOnBar.addDragResizeMoveHandler(new DragResizeMoveHandler() {	// implement a label link annotation(tagOnBar) onDragResizeMove listener		
			@Override
			public void onDragResizeMove(DragResizeMoveEvent event) {
				dragResizeReposition();	// set new annotation status size and position. 	
			}
		});
		
		
		tagOnBar.addMouseWheelHandler(new MouseWheelHandler() {	// implement a label link annotation(tagOnBar) onMouseWheel listener		
			@Override
			public void onMouseWheel(MouseWheelEvent event) {    // move the annotation time position 
				int wheelDelta = EventHandler.getWheelDelta();   // get the wheel rotation steeps
				tagOnBar.setLeft(tagOnBar.getLeft()+wheelDelta); // set the new label annotation link position within annotation progress bar
				dragResizeReposition();	 // set new annotation status size and position.
			}
		});
		
		
		tag.addAnnotationDescrTextChange(new AnnotationDescrTextChangeEventHandler() {
			
			@Override
			public void onKeyWordTextChange(AnnotationDescrTextChangeEvent event) {
				handleManagerTextChange.fireEvent(event);
				
			}
		});
		
		
		tag.addAnnotationSaveHandler(new AnnotationSaveEventHandler() { // implement onAnnotationSaved listener of AnnottaionTag			
			@Override
			public void onAnnotationSaved(AnnotationSaveEvent event) {
				//tag.setTimesegment(timeStart, timeStart); // sets new video annotation time interval segment
				//event.setTimesegment(timeStart, timeEnd);
				handleManagerAnnotationSaved.fireEvent(event);	// fire the AnnotationSaveEvent to the listener				 
			}
		});
		
		tag.addMouseWheelHandler(new MouseWheelHandler() { 	// implement onMouseWheel listener of AnnottaionTag			
			@Override
			public void onMouseWheel(MouseWheelEvent event) {  // move the annotation time position 
				int wheelDelta = EventHandler.getWheelDelta();  // get the wheel rotation steeps
				tagOnBar.setLeft(tagOnBar.getLeft()+wheelDelta); // set the new label annotation link position within annotation progress bar
				dragResizeReposition();	// set new annotation status size and position.		
				//tag.setTimesegment(timeStart, timeStart); // sets new video annotation time interval segment 
			}
		});
		
		tag.addAnnotationKeyWordBlur(new AnnotationKeywordBlurEventHandler() {
			
			@Override
			public void onAnnotationKeyWordBlur(AnnotationKeywordBlurEvent event) {
				handleManagerAnnotKeyWordBlur.fireEvent(event);				
			}
		});	
		
		
		xPosStart=(double) ((timeS/mediaDuration)* ((double)annotationTagBar.getOffsetWidth()));   // sets the start position of annotation link label
		xPosEnd=(double) ((timeEnd/mediaDuration)*((double)annotationTagBar.getOffsetWidth())); // sets the end position of annotation link label
		tagOnBar.setRect((int)xPosStart, yPosTagOnBar, (int) (xPosEnd-xPosStart), HEIGHT_TAGONBAR); // sets the default size of annotation link label
		annotationTagBar.addChild(tagOnBar); // insert annotation link label on annotation progress bar		
		tagOnBar.draw(); // draw the annotation link label 
		visible=true;  // set the annotation visible status as true.
		tagOnBar.setStyleName("TagOnBarBox"); // set annotation link label style.
		
	}
	
	
	/**
	 * this method sets the annotation time start value
	 * @param value : new annotation time start value to set
	 */
	public void setTimeStart(float value){
		timeStart=value;
	}
	
	
	/**
	 * this method sets the annotation time end value
	 * @param value : new annotation time end value to set
	 */
	public void setTimeEnd(float value){
		timeEnd=value;
	}
	
	
	/**
	 * this method gets the annotation time start value
	 * @return double value of annotation time start 
	 */
	public double getTimeStart(){
		return(timeStart);
	}
	
	
	/**
	 * this method gets the annotation time end value
	 * @return double value of annotation time end 
	 */
	public double getTimeEnd(){
		return(timeEnd);
	}
	
	
	/**
	 * add AnnotationMoved handler. Occurs when the annotation position change
	 * @param handler: SaStriaCustomEvent handler
	 */
	public void addAnnotationMovedHandler(SaStriaCustomEventHandler handler){
		handleManager.addHandler(SaStriaCustomEvent.TYPE, handler);
	}

	
	/**
	 * gets the label link annotation X start position value
	 * @return label link annotation X start position integer value
	 */
	public int getXStartPos(){
		return (int) (xPosStart);
	}
	
	
	/**
	 * gets the label link annotation X end position value
	 * @return label link annotation X end position integer value
	 */
	public int getXEndPos(){
		return (int) (xPosEnd);
	}
	
	
	/**
	 * gets if the annotation size position interval is included in a given x coordinate value passed as 
	 * input parameter
	 * @param xTime : x coordinate integer value used to verify if the annotation size position interval
	 * is included in a given x coordinate
	 * @return true if  annotation size position interval is included in a given x coordinate value
	 * passed as input parameter, false otherwise
	 */
	public boolean isInTimeZone(int xTime){
		boolean retValue;
		if((xPosStart<=xTime) && (xPosEnd>=xTime)) //if  annotation size position interval is included in a given x coordinate value
			retValue=true;
		else
			retValue=false;
		return(retValue);
	}

	
	/**
	 * show the annotation and open it as animation
	 */
	public void showAnnotation(){
		tag.forceDraw();
		visible=true;		
	}

	
	/**
	 * hide the annotation and close it as animation
	 */
	public void hideAnnotation(){
		tag.forceHide();
		visible=false;
		//tagOnBar.setContents("Hide");
		//tag.addContentToLabelSaStria("Hide");
	}
	
	
	/**
	 * return the annotation visible status
	 * @return true if annotation is visible, false otherwise.
	 */
	public boolean isVisible(){
		return visible;
	}
	
	
	/**
	 * add AnnotationSave handler. Occurs when the users makes double click on annotation for 
	 * close and save it.
	 * @param handler: AnnotationSaveEvent handler
	 */
	public void addAnnotationSaveHandler(AnnotationSaveEventHandler handler){
		handleManagerAnnotationSaved.addHandler(AnnotationSaveEvent.TYPE, handler);
	}
	
	
	
	/**
	 * set, save and update the status of annotation according to the play position time
	 * at the moment that the annotation was saved. The play position time is given as input 
	 * @param timeSaved play position time at the moment that the annotation was saved.
	 */
	public void setSizeAfterSave(double timeSaved){
		timeEnd=timeSaved;
		xPosStart=(float) ((timeStart/mediaDuration)*annotationTagBar.getOffsetWidth());
		xPosEnd=(float) ((timeEnd/mediaDuration)*annotationTagBar.getOffsetWidth());
		tagOnBar.setRect((int)xPosStart, yPosTagOnBar, (int) (xPosEnd-xPosStart), HEIGHT_TAGONBAR);		
		tagOnBar.draw();	
		// fire onAnnotationMoved event to alert listener. Used only for setting preview video segment
		// timestart and timeEnd 
		//handleManager.fireEvent(new SaStriaCustomEvent(evidenziableTag,previewIndex,timeStart,timeEnd)); 
		
	}
	
	
	/**
	 * sets the text caption of AnnotationTag
	 * @param value the string to set as caption.
	 */
	public void setContentValue(String value){
		tag.setContentValue(value);
		
	}
	
	
	/**
	 * sets the index of this annotation on array list of annotations
	 * @param value index of this annotation on array list of annotations as integer value
	 */
	public void setIndexOnList(int value){
		indexOnList=value;
	}
	
	
	/**
	 * fets the index of this annotation on array list of annotations
	 * @return index of this annotation on array list of annotations as integer value
	 */
	public int getIndexOnList(){
		return indexOnList;
	}
	
	/**
	 * Gets annotation preview index on annotation preview panel list.
	 * @return integer value of annotation preview index on annotation preview panel list.
	 */
	public int getPreviewIndex(){
		return (previewIndex);
	}
	
	 /**
	 * This method add a AnnotationDescrTextChangeEventHandler handler. This is executed when the annotation
	 * description change on AnnotationTag
	 * @param handler: the AnnotationDescrTextChangeEventHandler handler
	 */
	public void addAnnotationDescrTextChange(AnnotationDescrTextChangeEventHandler handler){
		handleManagerTextChange.addHandler(AnnotationDescrTextChangeEvent.TYPE, handler);
	}
	
	/**
	 * This method add a AnnotationKeywordBlurEventHandler handler. This is executed when the annotation
	 * description change on AnnotationTag
	 * @param handler: the AnnotationKeywordBlurEventHandler handler
	 */
	public void addAnnotationKeyWordBlur(AnnotationKeywordBlurEventHandler handler){
		handleManagerAnnotKeyWordBlur.addHandler(AnnotationKeywordBlurEvent.TYPE, handler);
	}
	
	
}
